
#include "sc_gui.h"

///DMA中断完成标志
#define dma_wait_ok()  //do{}while(JL_SPI1->CON& (1<<13))

extern void LCD_DMA_Fill_COLOR(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 *color);

//底层接口，与lvgl接口一样
void LCD_DMA_color(int xs, int ys, int xe, int ye, u16 *color)
{
#if 0
    dma_wait_ok();
    LCD_DMA_Fill_COLOR( xs,  ys,  xe,  ye,color);
#else
    //-----------------无DMA------------------------
    // LCD_SetWindows(xs, ys,xe, ye);
    for(int y = ys; y <=ye; y++)
    {
        for(int x = xs; x <=xe; x++)
        {
            gui->bsp_pset (x,y,*color);
            // LCD_Write_Dat16(*color);	//写入数据
            color++;
        }
    }
#endif
}


///SC_Refresh刷屏接口
void SC_Refresh(int xs, int ys,uint16_t w, uint16_t h,uint16_t *buf)
{

#if LCD_DMA_WAP
    uint32_t len=w*h;
    for(i=0; i<len; i++)
    {
        if(buf[i])
        {
            buf[i]=buf[i]>>8|buf[i]<<8;    //高低位WAP
        }
    }
#endif // 1
    dma_wait_ok();
    LCD_DMA_color(xs, ys,xs+w-1, ys+h-1,buf);
    if(gui->dma_i)
    {
        if(gui->dma_prt!=gui->pfb_buf)
        {
            gui->dma_prt= gui->pfb_buf;
        }
        else
        {
            gui->dma_prt= gui->pfb_buf+SC_PFB_BUF_SIZE/2;
        }
        gui->dma_i = 0;
    }
}

/**fun: 快速初始化*/
static inline void SC_pfb_init(SC_tile *dest,uint32_t colour)
{
    int len=dest->w*dest->h;
    colour=colour<<16|colour;
    for(int i=0; i<len/2; i++)
    {
        ((uint32_t *)dest->buf)[i]=colour;
    }
    dest->buf[len-1]=colour;
}

/**fun: pfb分割*/
void SC_pfb_clip(SC_tile *clip, int xs,int ys,int xe,int ye,uint16_t colour)
{
    static uint16_t addr=0;
    uint16_t width= xe-xs+1;
    uint16_t height=ye-ys+1;
    if(xs<0) xs=0;
    if(ys<0) ys=0;
    int max_height =   SC_PFB_BUF_SIZE/(width*2); // 根据帧缓冲区大小计算最大高度
    clip->num = (height + max_height - 1) / max_height; // 向上取整
    if(clip->stup<clip->num)
    {
        addr=addr>0? 0: SC_PFB_BUF_SIZE/2;
        clip->buf= &gui->pfb_buf[addr];
        clip->xs = xs;
        clip->ys = ys + clip->stup* max_height;
        clip->w  = width;

        if (clip->stup == clip->num-1)
        {
            clip->h = height - (clip->num-1) * max_height; // 最后一个分段可能高度不同
        }
        else
        {
            clip->h = max_height;
        }
    }
    SC_pfb_init(clip,colour);
    // printf("x=%d,y=%d,w=%d,h=%d clip->num=%d clip->stup=%d\r\n",clip->xs,clip->ys,clip->w,clip->h,clip->num,clip->stup);
}

///计算相交区
int SC_pfb_intersection(SC_tile *dest,SC_ARER *p,int xs,int ys,int xe,int ye)
{
    p->ys= SC_MAX(ys,dest->ys);             //ys边界限定
    p->ye= SC_MIN(ye,dest->ys+dest->h-1);   //ye边界限定
    if(p->ys>p->ye) return 0;
    p->xs= SC_MAX(xs,dest->xs);            //xs边界限定
    p->xe= SC_MIN(xe,dest->xs+dest->w-1);  //xe边界限定
    if(p->xs>p->xe) return 0;

    return 1;     //相交

}
/**fun: pfb输出到屏，skip跳过背景像素*/
int SC_pfb_Refresh(SC_tile *dest, uint8_t skip)
{
    int width =  dest->w;
    int height = dest->h;
    uint16_t *buf=dest->buf;

    if(++dest->stup>=dest->num)
    {
        dest->stup=0;   //记录刷新位置
    }
    if(skip==0)
    {
        SC_Refresh(dest->xs,dest->ys,width, height,buf);
        return dest->stup;
    }
    ///用于只刷边框或圆环，跳过中间象素拆行刷
    for(int y=dest->ys; y<dest->ys+height; y++)
    {
        int len=0;
        int st=-1;
        buf=&dest->buf[(y-dest->ys)*width];
        for(int x=0; x<width; x++)
        {
            if(buf[x]==gui->bkc)              //skip
            {
                while(buf[x+1]==gui->bkc) x++;
                if(len)
                {
                    SC_Refresh(dest->xs+st,y,len,1,&buf[st]);
                }
                len=0;
                st=-1;
            }
            else
            {
                if(st==-1) st=x;
                len++;
            }
        }
        if(len)
        {
            SC_Refresh(dest->xs+st,y,len, 1, &buf[st]);
        }
    }
    return dest->stup;
}



//图片解压缩显示，压缩数据支持透明，暂不支持作背景
void SC_Show_Image_zip(int xs,int ys,SC_img_zip *zip,uint16_t bc)
{
    uint16_t r,g,b,c=0;
    uint16_t dat16,unzip=0;
    uint16_t rep_cnt=0;
    u32 n=0;
    int xe=xs+zip->w-1;
    const u8 *buf=zip->map;
    uint16_t bak_alpha=gui->alpha;
    gui->alpha=255;
    while(n<zip->len)
    {
        if(buf[n]&0x20)
        {
            dat16=(buf[n+1]<<8)|buf[n];
            if(unzip==dat16)
            {
                n+=2;
                rep_cnt=(buf[n]<<8)|buf[n+1];  //重复的长度
                while(rep_cnt)
                {
                    rep_cnt--;
                    gui->dma_prt[gui->dma_i++]= c;
                    if(gui->dma_i>=zip->w)
                    {
                        gui->Refresh(xs, ys,gui->dma_i, 1,gui->dma_prt);  //gui->dma_i=0
                        ys++;
                    }
                }
            }
            else
            {
                unzip= dat16;
                gui->dma_prt[gui->dma_i++]=  unzip;
            }
            n+=2;
        }
        else
        {
            b=zip->map[n];
            r=(b<<5)&0x1800;
            g=(b<<3)&0x00e3;
            c=unzip^(r+g+(b&0x03));
            gui->dma_prt[gui->dma_i++]=  c;
            n++;
        }
        if(gui->dma_i>=zip->w)
        {
            gui->Refresh(xs,ys,gui->dma_i, 1,gui->dma_prt);
            ys++;
        }
    }
    gui->alpha=bak_alpha;
}
////RGB565图片数据压缩,返回压缩后的尺寸，上位机算法
//u32 RGB565_zip_in(u8 *buf,const u8 *map,u32 w,u32 h)
//{
//    u8 r,g,b;
//    u32 n=0;
//    u32 len=w*h;
//    uint16_t xor,mask=(~0x18e3);
//    uint16_t *dat=(uint16_t*)map;
//    //压缩：两个像素高位相同异或后高位为0
//    // R      G      B
//    //00011 000 11x 00011   x=1表示unzip    ff 1f
//    //000rr 000ggg 000bb   压缩为u8格式rrxgggbb
//    //解压：判断压缩标志进行异或还原
//    //rrxgggbb 解压回uint16_t格式000rr 000ggg 000bb
//    uint16_t unzip=dat[0]|0x0020;     //第一字节不压缩
//    buf[n++]=(unzip);
//    buf[n++]=unzip>>8;
//    u32 rep_cnt=0;
//    for(u32 i=1; i<len; i++)
//    {
//        xor= unzip^dat[i];
//        if(!(xor&mask))             //异或判断数据相似
//        {
//            r=(xor&0x1800)>>5;
//            g=(xor&0x00e0)>>3;
//            b=xor&0x0003;
//            buf[n++]=r|g|b;        //压缩为u8格式
//            //---------完全相等压缩---------------
//            rep_cnt=0;
//            while((dat[i])==(dat[rep_cnt+i+1]))
//            {
//                if(++rep_cnt>=0x1fff) break; //长度限制高位用作0x0020标志
//                if(rep_cnt+i>=len)    break;
//            }
//            if(rep_cnt>=4)                     //4个重复才压缩
//            {
//                buf[n++]= unzip;
//                buf[n++]= unzip>>8;
//                // printf("\r\nrep_cnt=%d n=%d",rep_cnt,n);
//                buf[n++]=(rep_cnt>>8);         //高低位互换0xff1f
//                buf[n++]=(rep_cnt);
//                i+=rep_cnt;
//            }
//        }
//        else
//        {
//            unzip=dat[i]|0x0020;
//            buf[n++]=unzip;
//            buf[n++]=unzip>>8;
//        }
//    }
//    len<<=1;
//    // printf("\r\n map_len=%d,buf_len=%d zip=%f/100  \r\n",len,n,(n*100/(float)len));
//    return n;
//}




